import os
import struct
import logging

class BinFileParser:
    """BIN文件解析器公共类
    提供BIN文件读取、解析功能，支持指定偏移量和连续读取
    """
    def __init__(self, filepath):
        """初始化BIN文件解析器
        Args:
            filepath (str): BIN文件绝对路径
        Raises:
            FileNotFoundError: 当文件不存在时触发
        """
        if not os.path.exists(filepath):
            raise FileNotFoundError(f"BIN文件不存在: {filepath}")
        self.filepath = filepath
        self.file_size = os.path.getsize(filepath)
        self._current_offset = 0  # 当前读取偏移量，支持连续读取
        logging.info(f"初始化BIN解析器: {filepath}, 大小: {self.file_size}字节")

    def get_file_size(self):
        """获取文件总大小
        Returns:
            int: 文件大小(字节)
        """
        return self.file_size

    def parse(self, offset=None, read_size=None, continue_read=False):
        """解析BIN文件内容
        Args:
            offset (int): 读取偏移量(字节)，为None且continue_read=True时使用当前偏移量
            read_size (int): 读取字节数，默认读取剩余全部
            continue_read (bool): 是否从当前偏移量继续读取，默认False
        Returns:
            bytes: 读取的二进制数据
        Raises:
            ValueError: 当偏移量超出文件大小时触发
        """
        # 确定读取偏移量
        if continue_read:
            actual_offset = self._current_offset
        elif offset is not None:
            actual_offset = offset
        else:
            actual_offset = 0

        if actual_offset < 0 or actual_offset > self.file_size:
            raise ValueError(f"无效偏移量: {actual_offset}, 文件大小: {self.file_size}")

        remain_size = self.file_size - actual_offset
        if read_size and read_size > remain_size:
            logging.warning(f"读取大小({read_size})超过剩余数据({remain_size}), 将读取全部剩余数据")
            read_size = remain_size

        try:
            with open(self.filepath, 'rb') as f:
                f.seek(actual_offset)
                data = f.read(read_size) if read_size else f.read()
                # 更新当前偏移量
                self._current_offset = actual_offset + len(data)
                logging.debug(f"读取成功: 偏移={actual_offset}, 长度={len(data)}字节, 下次读取偏移={self._current_offset}")
                return data
        except Exception as e:
            logging.error(f"文件读取失败: {str(e)}")
            raise

    def get_current_offset(self):
        """获取当前读取偏移量
        Returns:
            int: 当前偏移量位置
        """
        return self._current_offset

    def reset_offset(self, new_offset=0):
        """重置当前读取偏移量
        Args:
            new_offset (int): 新偏移量值，默认0
        Raises:
            ValueError: 当偏移量无效时触发
        """
        if new_offset < 0 or new_offset > self.file_size:
            raise ValueError(f"无效偏移量: {new_offset}, 文件大小: {self.file_size}")
        self._current_offset = new_offset
        logging.info(f"偏移量已重置为: {new_offset}")

    def parse_with_header(self, offset=0, read_size=None):
        """解析BIN文件并提取前4字节作为32位整数头
        Args:
            offset (int): 读取偏移量
            read_size (int): 读取字节数
        Returns:
            tuple: (header_value, data) - 头值和数据
        """
        data = self.parse(offset, read_size)
        header_value = None
        if len(data) >= 4:
            header_value = struct.unpack('<i', data[:4])[0]
            logging.debug(f"解析头部值: {header_value}")
        return header_value, data

if __name__ == '__main__':
    # 示例用法
    logging.basicConfig(level=logging.DEBUG)
    m600t = m600_communicator.M600Communicator("COM8")
    # 初始化M600T
    m600t.InitRSU()
    # 发送BST连接OBU
    m600t.SendBST()
    # 取随机数 APDU = "AA 55 02 02 0A 70 00 02 78"
    randNum = m600t.read_obu_randnumber()



    # 连续读取示例
    parser = BinFileParser("../sw/OBUC513_App_V1.0.2_20250315.bin")

    data1 = parser.parse(read_size=1024, continue_read=True)  # 从0开始读取1024字节
    data2 = parser.parse(read_size=512, continue_read=True)   # 从1024开始读取512字节
    data3 = parser.parse(read_size=2048, continue_read=True)  # 从1536开始读取2048字节

    # 重置偏移量并读取
    parser.reset_offset(0x8000)
    data4 = parser.parse(read_size=1024)  # 从0x8000开始读取